﻿//==============================================================================
// File: LabelTextBox.cs
// Created: 2010-05-28
// Author: Piotr Włodek, Arek Świerczek
//==============================================================================
// This file is a part of MAMMOTH project.
// Copyright (C) 2010 AGH University of Science and Technology, Krakow.
// https://caribou.iisg.agh.edu.pl/trac/mammoth
//
// Mammoth is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Mammoth is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with Mammoth. If not, see http://www.gnu.org/licenses/.
//==============================================================================

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WpfRcp.Controls
{
    [TemplatePart(Name = LabelTextBox.PART_Label, Type = typeof(Label))]
    [TemplatePart(Name = LabelTextBox.PART_TextBox, Type = typeof(TextBox))]
    public class LabelTextBox : Control
    {
        private bool m_AcceptText = true;

        public const string PART_Label = "PART_Label";
        public const string PART_TextBox = "PART_TextBox";

        static LabelTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(LabelTextBox), new FrameworkPropertyMetadata(typeof(LabelTextBox)));
        }

        public bool IsEdited
        {
            get { return (bool)GetValue(IsEditedProperty); }
            set { SetValue(IsEditedProperty, value); }
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public event RoutedEventHandler TextAccepted
        {
            add { AddHandler(TextAcceptedEvent, value); }
            remove { RemoveHandler(TextAcceptedEvent, value); }
        }

        public event RoutedEventHandler TextRejected
        {
            add { AddHandler(TextRejectedEvent, value); }
            remove { RemoveHandler(TextRejectedEvent, value); }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            TextBox PART_TextBox = GetPART_TextBox();
            if (PART_TextBox != null)
            {
                PART_TextBox.KeyDown += PART_TextBox_KeyDown;
                PART_TextBox.LostKeyboardFocus += PART_TextBox_LostKeyboardFocus;
            }

            Label PART_Label = GetPART_Label();
            if (PART_Label != null)
            {
                PART_Label.PreviewMouseDoubleClick += PART_Label_PreviewMouseDoubleClick;
            }
        }

        private void PART_TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            if(m_AcceptText)
            {
                AcceptText();
            }
            else
            {
                RejectText();
            }
            m_AcceptText = true;
        }

        private void PART_TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.Key == Key.Enter)
            {
                m_AcceptText = true;
                Focus();
            }
            else if (e.Key == Key.Escape)
            {
                m_AcceptText = false;
                Focus();
            }
        }

        private void PART_Label_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
            {
                IsEdited = true;

                TextBox PART_TextBox = GetPART_TextBox();
                if (PART_TextBox != null)
                {
                    PART_TextBox.Text = Text;
                    PART_TextBox.Focus();
                    PART_TextBox.SelectAll();
                }
            }
        }

        private void AcceptText()
        {
            IsEdited = false;

            TextBox PART_TextBox = GetPART_TextBox();
            if (PART_TextBox != null)
            {
                if (Text != PART_TextBox.Text)
                {
                    Text = PART_TextBox.Text;
                    RaiseEvent(new RoutedEventArgs(TextAcceptedEvent));
                }
            }
        }

        private void RejectText()
        {
            IsEdited = false;

            TextBox PART_TextBox = GetPART_TextBox();
            if (PART_TextBox != null)
            {
                if (PART_TextBox.Text != Text)
                {
                    PART_TextBox.Text = Text;
                    RaiseEvent(new RoutedEventArgs(TextRejectedEvent));
                }
            }
        }

        protected virtual TextBox GetPART_TextBox()
        {
            TextBox PART_TextBox = Template.FindName(LabelTextBox.PART_TextBox, this) as TextBox;
            return PART_TextBox;
        }

        protected virtual Label GetPART_Label()
        {
            Label PART_Label = Template.FindName(LabelTextBox.PART_Label, this) as Label;
            return PART_Label;
        }

        #region Dependency Properties 
        
        public static readonly DependencyProperty IsEditedProperty =
            DependencyProperty.Register("IsEdited", typeof(bool), typeof(LabelTextBox), new UIPropertyMetadata(false));

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(LabelTextBox), new FrameworkPropertyMetadata((string)string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        #endregion

        #region Routed Events
        
        public static readonly RoutedEvent TextAcceptedEvent = EventManager.RegisterRoutedEvent("TextAccepted",
                                                                                                RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(LabelTextBox));

        public static readonly RoutedEvent TextRejectedEvent = EventManager.RegisterRoutedEvent("TextRejected",
                                                                                                RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(LabelTextBox));

        #endregion
    }
}